/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package evocarcassonne.core.generator;

import evocarcassonne.core.utils.Card;
import evocarcassonne.core.utils.Rand;
import evocarcassonne.core.utils.ZoneType;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement.DEFAULT;

/**
 *
 * @author nobpn
 */
public class TilePattern2 {

    ZoneType type;
    boolean deadEnd = false;
    List<Integer> deadEnds;
    int touch = -1;
//    List<Integer> linkedMainZones;
    List<List<Integer>> newLinks2;
    List<Integer> removeFromLinks;
    List<Integer> addToMain;
    List<Integer> pawns;
    int rotation;
    int card;
    public List<Integer> otherCards;

    public TilePattern2() {
//        linkedMainZones = new ArrayList();

        deadEnds = new ArrayList();
        newLinks2 = new ArrayList();
        removeFromLinks = new ArrayList();
        addToMain = new ArrayList();
        pawns = new ArrayList();
        otherCards = new ArrayList();
    }

    private TilePattern2(TilePattern2 tp) {
        this();
        card = tp.card;
        type = tp.type;
        rotation = tp.rotation;
        touch = tp.touch;
        deadEnd = tp.deadEnd;
    }

    public static TilePattern2 doubleElt(int rot) {

        int scenario = Rand.getInt(2);

//        System.out.println("scenario:"+scenario);
//        scenario = 0;

        switch (scenario) {

            case 0:
                return doubleRoad(rot);
//                break;

            case 1:
                return doubleCity(rot);

            case 2:
//                return touchRoadE2S(rot);
            default:
                return doubleCity(rot);
        }
    }

    static TilePattern2 simpleElt(int rot) {

        int scenario = Rand.getInt(3);

//        System.out.println("scenario:"+scenario);
        scenario = 1;

        switch (scenario) {

            case 0:
                // Simple Double Simple
                return simpleCity(rot);
//                break;

            case 1:
                return simpleDeadEndRoad(rot);

//                break;
            default:
                return simpleCity(rot);

        }

//        return simpleRoad(rot);
    }

    public static TilePattern2 simpleCity(int rot) {

        TilePattern2 tp = new TilePattern2();

        tp.type = ZoneType.CITY;
        tp.rotation = rot;
        tp.card = Card.N;
        tp.pawns.add(Card.N);

        tp.removeFromLinks.add(Card.N);

        tp = rotate(tp);

        return tp;
    }

    static TilePattern2 touchRoadW2N(int rot) {
        TilePattern2 tp = new TilePattern2();

        tp.type = ZoneType.ROAD;
        tp.rotation = rot;

        tp.card = Card.W;
        tp.removeFromLinks.add(Card.W);

        tp.addToMain.add(Card.WSW);

        tp.touch = Card.N;

        tp = rotate(tp);

        return tp;
    }

    static TilePattern2 touchRoadE2S(int rot) {
        TilePattern2 tp = new TilePattern2();

        tp.type = ZoneType.ROAD;
        tp.rotation = rot;

        tp.card = Card.E;
        tp.removeFromLinks.add(Card.E);

        tp.addToMain.add(Card.ESE);

        tp.touch = Card.S;

        tp = rotate(tp);

        return tp;
    }

    static TilePattern2 touchRoadOpposite(int rot) {
        TilePattern2 tp = new TilePattern2();

        tp.type = ZoneType.ROAD;
        tp.rotation = rot;

        tp.card = Card.E;

        tp.removeFromLinks.add(Card.E);
        tp.removeFromLinks.add(Card.N);
        tp.removeFromLinks.add(Card.S);

        List<Integer> leftField = new ArrayList();
        leftField.add(Card.ENE);
        leftField.add(Card.N);
        tp.newLinks2.add(leftField);

        List<Integer> rightField = new ArrayList();
        rightField.add(Card.ESE);
        rightField.add(Card.S);
        tp.newLinks2.add(rightField);

        tp.touch = Card.W;

        tp = rotate(tp);

        return tp;
    }

    private static TilePattern2 simpleDeadEndRoad(int rot) {

        TilePattern2 tp = new TilePattern2();

        tp.type = ZoneType.ROAD;
        tp.rotation = rot;

        tp.removeFromLinks.add(Card.N);
        tp.card = Card.N;

        tp.addToMain.add(Card.NNW);
        tp.addToMain.add(Card.NNE);

        tp.pawns.add(Card.N);
        tp.pawns.add(Card.NNW);

        tp.deadEnd = true;
        tp.deadEnds.add(Card.N);

        tp = rotate(tp);

        return tp;
    }

    private static TilePattern2 doubleCity(int rot) {
        TilePattern2 tp = new TilePattern2();

        tp.type = ZoneType.CITY;
        tp.rotation = rot;

        //liens
        List<Integer> link = new ArrayList();
        link.add(Card.S);
        link.add(Card.E);

        tp.newLinks2.add(link);

        tp.removeFromLinks.add(Card.S);
        tp.removeFromLinks.add(Card.E);


        tp = rotate(tp);

        return tp;
    }

    public static TilePattern2 doubleRoad(int rot) {
        TilePattern2 tp = new TilePattern2();

        tp.type = ZoneType.ROAD;
        tp.rotation = rot;

        // link ROAD
        List<Integer> link = new ArrayList();
        link.add(Card.S);
        link.add(Card.E);
        tp.newLinks2.add(link);

        tp.removeFromLinks.add(Card.S);
        tp.removeFromLinks.add(Card.E);

        //link smallFields
        List<Integer> smallfield = new ArrayList();
        smallfield.add(Card.ESE);
        smallfield.add(Card.SSE);

        tp.newLinks2.add(smallfield);

        tp.addToMain.add(Card.ENE);
        tp.addToMain.add(Card.SSW);

        tp = rotate(tp);

        return tp;
    }

    public static TilePattern2 tripleElt(int rot) {

        int scenario = Rand.getInt(2);
//        scenario = 1;

        switch (scenario) {
            case 0:
                return tripleRoad(rot);
            case 1:
                return tripleCity(rot);
            default:
                return tripleCity(rot);
        }
    }

    private static TilePattern2 tripleCity(int rot) {
        TilePattern2 tp = new TilePattern2();

        tp.rotation = rot;
        tp.type = ZoneType.CITY;

        tp.card = Card.S;
        tp.pawns.add(Card.S);

        List<Integer> link = new ArrayList();
        link.add(Card.S);
        link.add(Card.E);
        link.add(Card.W);
        tp.newLinks2.add(link);

        tp.removeFromLinks.add(Card.S);
        tp.removeFromLinks.add(Card.E);
        tp.removeFromLinks.add(Card.W);

        tp.otherCards.add(Card.S);
        tp.otherCards.add(Card.E);
        tp.otherCards.add(Card.W);


        tp = rotate(tp);


        return tp;
    }

    private static TilePattern2 tripleRoad(int rot) {
        TilePattern2 tp = new TilePattern2();

        tp.type = ZoneType.ROAD;
        tp.rotation = rot;

        tp.card = Card.S;
        tp.otherCards.add(Card.E);
        tp.otherCards.add(Card.W);

        tp.pawns.add(Card.S);
        tp.pawns.add(Card.SSE);
        tp.pawns.add(Card.SSW);

        // link ROAD
        List<Integer> link = new ArrayList();
        link.add(Card.S);
        link.add(Card.E);
        link.add(Card.W);
        tp.newLinks2.add(link);

        tp.removeFromLinks.add(Card.S);
        tp.removeFromLinks.add(Card.E);
        tp.removeFromLinks.add(Card.W);

        //link smallFields
        List<Integer> smallfield1 = new ArrayList();
        smallfield1.add(Card.ESE);
        smallfield1.add(Card.SSE);
        tp.newLinks2.add(smallfield1);

        //link smallFields
        List<Integer> smallfield2 = new ArrayList();
        smallfield2.add(Card.SSW);
        smallfield2.add(Card.WSW);
        tp.newLinks2.add(smallfield2);


        tp.addToMain.add(Card.ENE);
        tp.addToMain.add(Card.WNW);

        tp = rotate(tp);

        return tp;
    }

    private static TilePattern2 rotate(TilePattern2 tp) {

        TilePattern2 rpt = new TilePattern2(tp);

        for (List<Integer> link : tp.newLinks2) {

            List<Integer> newlink = new ArrayList();

            for (Integer oldCard : link) {

                int newCard = (oldCard - tp.rotation + 12) % 12;
                newlink.add(newCard);
            }
            rpt.newLinks2.add(newlink);
        }

        // Add To Main
        for (Integer oldCard : tp.addToMain) {
            int newCard = (oldCard - tp.rotation + 12) % 12;
            rpt.addToMain.add(newCard);
        }

        // Remove From Main
        for (Integer oldCard : tp.removeFromLinks) {
            int newCard = (oldCard - tp.rotation + 12) % 12;
            rpt.removeFromLinks.add(newCard);
        }

        //card
        int nC = (tp.card - tp.rotation + 12) % 12;
        rpt.card = nC;

        //pawns
        for (Integer oldCard : tp.pawns) {
            int newCard = (oldCard - tp.rotation + 12) % 12;
            rpt.pawns.add(newCard);
        }

        //pawns
        for (Integer oldCard : tp.otherCards) {
            int newCard = (oldCard - tp.rotation + 12) % 12;
            rpt.otherCards.add(newCard);
        }

//        for (Integer oldCard : tp.linkedMainZones) {
////        zones[(card - tp.rotation + zones.length) % zones.length];
//            int newCard = (oldCard - tp.rotation + 12) % 12;
//            rpt.linkedMainZones.add(newCard);
//        }

        if (tp.type == ZoneType.ROAD) {
            if (tp.deadEnd) {

                for (Integer oldCard : tp.deadEnds) {
                    int newCard = (oldCard - tp.rotation + 12) % 12;
                    rpt.deadEnds.add(newCard);
                }
            } else if (tp.touch != -1) {

                int newCard = (tp.touch - tp.rotation + 12) % 12;
                rpt.touch = newCard;


            } else {
//                for (List smallField : tp.newLinks) {
//
//                    List<Integer> newSmallField = new ArrayList();
//
//                    for (Object object : smallField) {
//
//                        Integer oldCard = (Integer) object;
//
//                        int newCard = (oldCard - tp.rotation + 12) % 12;
//                        newSmallField.add(newCard);
//                    }
//                    rpt.newLinks.add(newSmallField);
//                }
//                for (Integer oldCard : tp.linkedFieldsZones) {
////        zones[(card - tp.rotation + zones.length) % zones.length];
//                    int newCard = (oldCard - tp.rotation + 12) % 12;
//                    rpt.linkedFieldsZones.add(newCard);
//                }
            }
        }



        return rpt;
    }
}
